#include "../globals.h"

using namespace std;

void printUsage()
{
	cout << "Commandline argument for server:" << endl;
	cout << "-pn <port_number>" << endl;
	cout << "-cwnd <current_window>" << endl;
	cout << "-pl <packet loss probability>" << endl;
	cout << "-pc <packet corruption probability>" << endl;
}

int portnum = 0;
int cwnd = 0;
char filename[DATASIZE];
double pl = 0;
double pc = 0;

int main(int argc, char **argv)
{
	if (argc != 9)
	{
		printUsage();
		exit(1);
	}
	
	for (int i = 1; i < argc; i++)
	{
		if (strcmp(argv[i], "-pn") == 0)
		{
			i++;
			portnum = atoi(argv[i]);
		}
		else if (strcmp(argv[i], "-cwnd") == 0)
		{
			i++;
			cwnd = atoi(argv[i]);
		}
		else if (strcmp(argv[i], "-pl") == 0)
		{
			i++;
			pl = atof(argv[i]);
		}
		else if (strcmp(argv[i], "-pc") == 0)
		{
			i++;
			pc = atof(argv[i]);
		}
	}
	
	// get directory of server
	string serverDirectory = argv[0];
	serverDirectory = serverDirectory.substr(0,serverDirectory.find_last_of("\\/") + 1);
	
	server = new CServer(serverDirectory, portnum, cwnd, pl, pc);

	while( server->recvpacket() != -1 )
	{
		// following done so we can treat server->pendingsend().payload as cstring
		server->lastrecv().payload[server->lastrecv().length] = '\0'; // THIS IS BAD, WE ASSUME BUFFER NOT FULL!!!
		
		/*printf("Received packet from %s:%d\nData: %s\n\n", 
		       inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), server->pendingsend().payload);*/
		  		       
		if ( server->lastrecv().type == FILE_REQUEST )
		{
			// extract requested filename and append to server path
			strncpy(filename, server->lastrecv().payload, server->lastrecv().length);
			string filepath = serverDirectory + filename;
			
			// check if request file exists
			struct stat st;
			if (stat(filepath.c_str(), &st) == 0)
			{
				// file exists, send to client
				ifstream filetosend(filepath.c_str());
				if (filetosend.is_open())
				{
					cout << "FILE REQUEST: Starting to send file '" << filename << "' to client" << endl << endl;
					// get num chunks needed to send file
					unsigned int numChunks = st.st_size / DATASIZE;
					if (st.st_size % DATASIZE != 0)
					{
						// last chunk will not contain full data buffer
						numChunks++;
					}
					
					// send data over in chunks
					server->pendingsend().type = DATA;
					int lastseqnum = 0;
					for (unsigned int i = 0; i < numChunks; i++)
					{
						while (!server->canSendNew())
						{
							// do something to ensure we can send new
							// packet once we get out of here
							 
							// wait to recieve an ACK
							if ( server->recvpacket() == -1 )
							{
								perror("error: recvpacket() failed\n");
							}
						}
						
						// send new packet
						filetosend.read(server->pendingsend().payload, DATASIZE);
						streamsize bytesRead = filetosend.gcount();
						server->pendingsend().seqnum = lastseqnum;
						lastseqnum += bytesRead;
						server->pendingsend().length = bytesRead;
					
						if ( server->sendpacket() != -1 )
						{
						}
						else
						{
							perror("error: sendpacket() failed\n");
						}
					}
					
					// if we get here it means we have sent all chunk
					// wait for notification that all chunks in transmit have been sent
					while (!server->isDone())
					{
					}
					
					server->transferComplete();
					
					filetosend.close();
				}
				else
				{
					cout << "Failed to open file '" << filepath << "'" << endl;
				}
			}
			else
			{
				// file does not exist
				string failure = "Requested file '";
				failure += filename;
				failure += "' does not exist\n";
				server->pendingsend().type = ERROR;
				strcpy(server->pendingsend().payload, failure.c_str());
				server->pendingsend().length = failure.size();
				if ( server->sendpacket() == -1)
				{
					perror("error: sento() failed\n");
				}
			}
		}
		
		server->newTransfer();
	}
	
	exit(0);
}
		
